package com.yunji.coupon.engine;

import com.yunji.base.domain.BelongDO;
import com.yunji.common.utils.ConvertDataUtil;
import com.yunji.common.utils.TimeUtils;
import com.yunji.common.utils.bean.BeanUtils;
import com.yunji.coupon.bo.CouponBO;
import com.yunji.coupon.consumer.CouponConsumer;
import com.yunji.coupon.doamin.CouponDO;
import com.yunji.coupon.doamin.CouponRecordDO;
import com.yunji.coupon.doamin.CouponSiteDO;
import com.yunji.coupon.doamin.CouponTmplDO;
import com.yunji.coupon.dto.CouponSiteDTO;
import com.yunji.coupon.dto.CouponTmplCreateDTO;
import com.yunji.coupon.enums.*;
import com.yunji.coupon.vo.CouponTmplListVO;
import com.yunji.coupon.vo.CouponVO;
import org.apache.commons.compress.utils.Lists;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author : peter-zhu
 * @date : 2024/10/23 17:05
 * @description : 专做数据转换
 **/
public class CouponConvert {

    public static CouponTmplDO tmpl2DO(CouponTmplCreateDTO dto) {
        if (CouponSiteScopeEnum.SCOPE.getCode().equals(dto.getSiteScopeType())) {
            Assert.isTrue(!CollectionUtils.isEmpty(dto.getCouponSiteList()), "指定网点信息为空");
        }
        if (CouponSiteScopeEnum.EXCLUDE_SCOPE.getCode().equals(dto.getSiteScopeType())) {
            Assert.isTrue(!CollectionUtils.isEmpty(dto.getCouponSiteList()), "排除网点信息为空");
        }
        CouponTmplDO domain = new CouponTmplDO();
        BeanUtils.copyExcludeBase(dto, domain);
        return domain;
    }

    private static CouponTmplStatusEnum buildTmplStatusEnum(CouponTmplDO domain, long now) {
        CouponTmplStatusEnum status;
        if (domain.getReceiveTimeS().getTime() <= now && now <= domain.getReceiveTimeE().getTime()) {
            status = CouponTmplStatusEnum.RUNNING;
        } else if (domain.getReceiveTimeS().getTime() >= now) {
            status = CouponTmplStatusEnum.UN_START;
        } else {
            status = CouponTmplStatusEnum.OVER;
        }
        return status;
    }

    private static CouponStatusEnum buildStatusEnum(CouponDO domain, long now) {
        CouponStatusEnum status;
        if (CouponStatusEnum.UN_USED.getCode().equals(domain.getCouponStatus())) {
            if (now <= domain.getValidPeriodE().getTime()) {
                status = CouponStatusEnum.UN_USED;
            } else {
                status = CouponStatusEnum.INVALID;
            }
        } else {
            status = CouponStatusEnum.getByCode(domain.getCouponStatus());
        }
        return status;
    }

    public static CouponVO convert2CouponVO(CouponBO couponBO) {
        CouponVO couponVO = new CouponVO();
        CouponDO domain = couponBO.getDomain();
        CouponTmplDO tmplDO = couponBO.getTmplDO();
        BeanUtils.copyExcludeBase(domain, couponVO);
        BeanUtils.copyExcludeBase(tmplDO, couponVO);
        couponVO.setCouponType(CouponTypeEnum.getDescByCode(tmplDO.getCouponType()));
        CouponStatusEnum couponStatusEnum = buildStatusEnum(domain, couponBO.getNow().getTime());
        couponVO.setCouponStatus(couponStatusEnum.getCode());
        couponVO.setCouponStatusDesc(couponStatusEnum.getDesc());
        couponVO.setValidTime(TimeUtils.dateYmdHms(domain.getValidPeriodS()) + " ~ " + TimeUtils.dateYmdHms(domain.getValidPeriodE()));
        couponVO.setReason(couponBO.getReason());
        couponVO.setCouponId(domain.getCouponId());
        couponVO.setReceiveTime(TimeUtils.dateYmdHms(domain.getCreateTime()));
        return couponVO;
    }

    public static List<CouponTmplListVO> tmpl2VOList(List<CouponTmplDO> domainList) {
        List<CouponTmplListVO> voList = Lists.newArrayList();
        long now = new Date().getTime();
        domainList.forEach(domain -> {
            CouponTmplListVO vo = new CouponTmplListVO();
            BeanUtils.copyExcludeBase(domain, vo);
            vo.setDiscount(DiscountTypeEnum.showByCode(domain.getDiscountType(), domain.getDiscountValue().doubleValue()));
            vo.setCouponType(CouponTypeEnum.getDescByCode(domain.getCouponType()));
            vo.setReceiveTime(TimeUtils.dateYmdHms(domain.getReceiveTimeS()) + "~" + TimeUtils.dateYmdHms(domain.getReceiveTimeE()));
            if (ValidTimeTypeEnum.REGULAR.getCode().equals(domain.getValidTimeType())) {
                vo.setValidTime(TimeUtils.dateYmdHms(domain.getValidPeriodS()) + "~" + TimeUtils.dateYmdHms(domain.getValidPeriodE()));
            } else {
                vo.setValidTime("领取后" + domain.getValidDays() + "天内");
            }
            vo.setReceiveDesc(domain.getReceivedCount() + "/" + domain.getIssueCount());
            vo.setUsedDesc(String.valueOf(domain.getUsedCount()));
            CouponTmplStatusEnum couponTmplStatusEnum = buildTmplStatusEnum(domain, now);
            vo.setCouponStatusDesc(couponTmplStatusEnum.getDesc());
            vo.setCouponStatus(couponTmplStatusEnum.getCode());
            vo.setCreateTime(TimeUtils.dateYmdHms(domain.getCreateTime()));
            vo.setRecallFlag(domain.isRecallFlag());
            voList.add(vo);
        });
        return voList;
    }

    public static List<CouponSiteDO> sites2DOList(List<CouponSiteDTO> couponSiteList, CouponConsumer couponConsumer,Integer siteScopeType) {
        Map<Long, BelongDO> siteMap = couponConsumer.getBelongMap(
                ConvertDataUtil.list2FieldList(couponSiteList, CouponSiteDTO::getSiteBelongId));
        return couponSiteList.stream().map(csDTO -> {
            CouponSiteDO couponSiteDO = new CouponSiteDO();
            BeanUtils.copyExcludeBase(csDTO, couponSiteDO);
            couponSiteDO.setSiteScopeType(siteScopeType);
            BelongDO belong = siteMap.get(csDTO.getSiteBelongId());
            if (belong != null) {
                couponSiteDO.setSiteId(belong.getSiteId());
                couponSiteDO.setAgentId(belong.getAgentId());
            }
            return couponSiteDO;
        }).collect(Collectors.toList());
    }

    public static List<CouponSiteDTO> sites2DTOList(List<CouponSiteDO> couponSiteList) {
        return couponSiteList.stream().map(domain -> {
            CouponSiteDTO couponSiteDTO = new CouponSiteDTO();
            BeanUtils.copyExcludeBase(domain, couponSiteDTO);
            return couponSiteDTO;
        }).collect(Collectors.toList());
    }

    public static CouponRecordDO convert2Record(CouponDO couponDO, Long orderId, String orderCode, BigDecimal amt, String type) {
        CouponRecordDO couponRecordDO = new CouponRecordDO();
        BeanUtils.copyExcludeBase(couponDO, couponRecordDO);
        couponRecordDO.setOrderId(orderId);
        couponRecordDO.setOrderCode(orderCode);
        couponRecordDO.setCouponAmt(amt);
        couponRecordDO.setCouponRecordType(type);
        return couponRecordDO;
    }
}
